<template>
    <div class="input-table" v-clickoutside="handleHide">
      <div class="input-table-input" @click="disabled?this:handleShow()">
        <a-input
            :value="showValue"
            :disabled="disabled"
            class="select-table-input"
            :placeholder="placeholder"
            @change="inputValueChange"
            @click="()=>{this.modalVisible = true}"
        >
          <a-icon type="bars" style="color: rgba(0,0,0,.45)" slot="suffix"/>
        </a-input>
      </div>
      <a-modal v-model="modalVisible" title="选择数据" width="1100px" footer="null" :pagination="ipagination">
        <div style="position: absolute;left: 0;top: 45px;width: 100%;z-index: 10;white-space: nowrap;overflow-x: auto;">
          <template v-if="searchVisible">
            <a-input v-model="keyWords" placeholder="请输入关键字" style="width: 25%"/>
            <a-button type="primary" @click="search" style="margin:0 6px;" icon="search">搜索</a-button>
            <a-button  @click="reset" icon="sync">重置</a-button>
          </template>
          <a-table 
            ref="table" 
            size="small" 
            :scroll="scroll" 
            :columns="columns" 
            :dataSource="dataSource" 
            :customRow="onCustomRow" 
            :pagination="ipagination" 
            @change="handleTableChange"
            :rowKey="rowKey" 
            style="margin-top: 10px;">
              <span slot="renderSerial" slot-scope="text, record, index">{{ index + 1 }}</span>
          </a-table>
        </div>
      </a-modal>
    </div>
  </template>
  
  <script>
    import {filterObj, debounce} from '@/utils/util';
    const clickoutside = {
      // 初始化指令
      bind(el, binding, vnode) {
        function documentHandler(e) {
          // 这里判断点击的元素是否是本身，是本身，则返回
          if (el.contains(e.target)) {
            return false
          }
          // 判断指令中是否绑定了函数
          if (binding.expression) {
            // 如果绑定了函数 则调用那个函数，此处binding.value就是handleHide方法
            binding.value(e)
          }
        }
        // 给当前元素绑定个私有变量，方便在unbind中可以解除事件监听
        el.__vueClickOutside__ = documentHandler;
        document.addEventListener('click', documentHandler)
      },
      unbind(el, binding) {
        // 解除事件监听
        document.removeEventListener('click', el.__vueClickOutside__);
        delete el.__vueClickOutside__
      }
    };
  
    export default {
      name: 'PopoverGrid',
      props: {
        placeholder: {
          type: String,
          required: false,
          default: ''
        },
        disabled: {
          type: Boolean,
          required: false,
          default: false,
        },
        url: {
          type: String,
          required: false,
          default: ''
        },
        parameter:{},
        columns: {
          type: Array,
          required: false,
          default: () => [],
        },
        value: {
          type: String,
          required: false,
          default: '',
        },
        saveCode: {
          type: String,
          required: false,
          default: 'id',
        },
        showCode: {
          type: String,
          required: false,
          default: 'name',
        },
        sorter: {
          type: Object,
          required: false,
          default: () => {
          },
        },
        queryParams: {
          type: Object,
          required: false,
          default: () => {
          },
        },
        pageSize: {
          type: Number,
          required: false,
          default: 10,
        },
        rowKey: {
          type: String,
          required: false,
          default: "id",
        },
        scroll: {
          type: Object,
          required: false,
          default: function () {
            return {x: 200, y: 500}
          },
        },
        searchVisible: {
          type: Boolean,
          required: false,
          default: false,
        }
      },
      directives: {clickoutside},
      data() {
        return {
            modalVisible: false,
            tableVisible: false,
            dataSource: [],
            keyWords:'',
            /* 分页参数 */
            ipagination: {
                current: 1,
                pageSize: this.pageSize,
                pageSizeOptions: ['5', '10', '15', '20', '30'],
                showSizeChanger: true,
                total: 0
            },
            isorter: this.sorter, /* 排序参数 */
            showValue: '',//展示值
            saveValue: '',//保存值
            record: {},
            // 存储各个div的style
            style: {
                tableDiv: {
                position: "absolute",
                zIndex: "999",
                backgroundColor: "#ffffff",
                border: "#dedede 1px solid",
                padding: "5"
                },
            },
        }
      },
      computed: {
        getTableVisible() {
          if (this.tableVisible) {
            return 'showTable';
          } else {
            return 'hideTable';
          }
        },
      },
      watch: {
        value: {
          immediate: true,
          handler(val) {
            if (val) {
              this.saveValue = val;
              this.loadData(1)
            } else {
              this.saveValue = '';
              this.showValue = '';
              this.record = {};
              this.$emit('getRecord', {});
              this.loadData(1);
            }
          }
        },
        pageSize: {
          immediate: true,
          handler() {
            this.ipagination.pageSize = this.pageSize
          },
        },
        columns: {
          handler(val) {
            val.forEach((item,index) => {
              if (index !== 0) {
                Object.assign(item, { width: 200, ellipsis: true })
              }
            })
            this.columns = val
          }
        }
      },
      methods: {
        search() {
          let params = this.getQueryParams()
          this.$post(this.url, params).then(res => {
            let newData = this.parseData(res.data)
            if (res.statusCode === 200) {
              this.dataSource = newData.data ? newData.data : newData;
              this.ipagination.total = newData.data ? newData.data.length : newData.length;
            }
          })
        },
        reset() {
          this.keyWords = ''
          let params = this.getQueryParams()
          this.$post(this.url, params).then(res => {
            let newData = this.parseData(res.data)
            if (res.statusCode === 200) {
              this.dataSource = newData.data ? newData.data : newData;
              this.ipagination.total = newData.data ? newData.data.length : newData.length;
            }
          })
        },
        loadData(arg) {
        if (!this.url) {
            return 
          }
          //加载数据 若传入参数1则加载第一页的内容
          if (arg === 1) {
            this.ipagination.current = 1;
          }
          var params = this.getQueryParams();//查询条件
          this.$post(this.url, params).then(res => {
            let newData = this.parseData(res.data)
            if (res.statusCode === 200) {
              this.dataSource = newData.data ? newData.data : newData;
              this.ipagination.total = newData.data ? newData.data.length : newData.length;

              if (this.value) {
                let saveCode = this.saveCode
                let showCode = this.showCode
                let data = this.dataSource.find((obj) => obj[saveCode] == this.value)
                this.showValue = data[showCode]
              }
            }
          })
      },
      // JSON格式数据转JS格式
      parseData(data) {
        try {
          // 尝试 JSON.parse 两次
          const parsedData = JSON.parse(JSON.parse(data));
          return parsedData;
        } catch (error) {
          try {
            // 如果报错，再尝试 JSON.parse 一次
            const parsedData = JSON.parse(data);
            return parsedData;
          } catch (error) {
            // 如果再次报错，返回原始数据
            return data;
          }
        }
      },
        getQueryParams() {
          let queryParam = {};
          queryParam = {
            keyWords: this.keyWords,
            ...this.parameter,
          };
          if (this.queryParams) {
            Object.assign(queryParam, this.queryParams)
          }
          var param = Object.assign({}, queryParam, this.isorter, this.filters);
          param.pageNo = this.ipagination.current;
          param.pageSize = this.ipagination.pageSize;
          return filterObj(param);
        },
        getQueryField() {
          //TODO 字段权限控制
          var str = "id,";
          this.columns.forEach(function (value) {
            str += "," + value.dataIndex;
          });
          return str;
        },
        handleHide() { // 点击除了页面其他地方关闭车型选择
          this.tableVisible = false;
        },
        handleShow() {
          this.$emit('click', this.saveValue);
          this.loadData(1);
          this.tableVisible = true;
        },
        onCustomRow(record) {
          return {
            props: {},
            on: {
              click: () => {
                this.record = record;
                this.saveValue = this.record[this.saveCode];
                this.showValue = this.record[this.showCode];
                this.$emit('select', this.saveValue);
                this.$emit('input', this.saveValue);
                this.$emit('change', this.saveValue);
                this.$emit('getRecord', this.record);
                this.handleHide();
                this.modalVisible = false;
              },
            },
          };
        },
        inputValueChange(e) {
          this.showValue = e.target.value;
          if (!this.disabled) this.handleShow();
          this.$emit('inputChange', e.target.value);
          if (this.showValue === null || this.showValue === undefined || this.showValue === '') {
            this.clear();
          }
          debounce(() => {
            this.loadData(1)
          }, 500);
        },
        getShowValue() {
          return this.showValue;
        },
        getSaveValue() {
          return this.saveValue;
        },
        clear() {
          this.saveValue = '';
          this.showValue = '';
          this.record = {};
          this.$emit('select', '');
          this.$emit('input', '');
          this.$emit('change', '');
          this.$emit('getRecord', {});
          this.handleHide();
        },
        handleTableChange(pagination, filters, sorter) {
          //分页、排序、筛选变化时触发
          //TODO 筛选
          if (Object.keys(sorter).length > 0) {
            this.isorter.column = sorter.field;
            this.isorter.order = "ascend" == sorter.order ? "asc" : "desc"
          }
          this.ipagination = pagination;
          this.loadData();
        },
        tableDivStyle() {
          let style = Object.assign({}, this.style.tableDiv)
          let width1 = this.getDivTopLength();
          let width2 = this.realTrWidth();
          if (width1 > width2) {
            style['width'] = width2 + "px";
          } else {
            style['width'] = width1 + "px";
          }
          return style
        },
  
        //table 列总宽度
        realTrWidth() {
          let calcWidth = 0
          this.columns.forEach((column, i) => {
            let {type, width} = column
            // 隐藏字段不参与计算
            if (typeof width === 'number') {
              calcWidth += width
            } else if (typeof width === 'string') {
              width = width.replace("px", "");
              calcWidth += Number(width)
            } else {
              calcWidth += 120
            }
          })
          return calcWidth
        },
        //获取指定第v据屏幕右侧宽度
        getDivTopLength() {
          return 600;
        },
      },
      // 在组件内定义 指定父组件调用时候的传值属性和事件类型
      model: {
        prop: 'value',
        event: 'input'
      }
    }
  </script>
  <style scoped lang="less">
    .input-table {
      .showTable {
        display: block;
      }
      .hideTable {
        display: none;
      }
      .select-table-input {
        margin-right: 20px;
      }
    }
    /deep/.ant-table-pagination.ant-pagination {
      background-color: rgba(255, 255, 255, 0.5);
      margin-bottom: 50px !important;
      margin-right: 5px !important;
    }
  </style>
  